package org.deadline.model.user;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.deadline.model.baseapp.Event;
import org.deadline.model.baseapp.Principal;
import org.deadline.model.baseapp.UserApplicationConfiguration;
import org.deadline.model.baseapp.UserPreference;
import org.deadline.model.config.Enumeration;
import org.deadline.model.config.Industry;
import org.deadline.model.config.JobTitle;
import org.deadline.model.config.LdapServer;
import org.springframework.format.annotation.DateTimeFormat;

import flexjson.JSONDeserializer;
import flexjson.JSONSerializer;

@Entity
@PrimaryKeyJoinColumn(name="id")
public class Person extends Principal {

    @NotNull
    @Size(min = 6, max = 255)
    private String userName;

    @NotNull
    @Size(min = 6, max = 255)
    private String displayName;

    @ManyToOne
    private Enumeration personType;

    @ManyToOne
    private LdapServer ldapServer;

    @NotNull
    @Size(min = 6, max = 255)
    private String password;

    @NotNull
    @Size(min = 6, max = 255)
    private String salt;

    @NotNull
    @Size(min = 2, max = 100)
    private String firstName;

    @Size(max = 100)
    private String middleName;

    @NotNull
    @Size(min = 2, max = 100)
    private String lastName;

    
    @Size(max = 20)
    private String namePrefix;

    
    @Size(max = 100)
    private String jobDescription;

    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "M-")
    private Date dateOfBirth;

    @ManyToOne
    private Enumeration gender;

    @ManyToOne
    private Person createdBy;

    @ManyToOne
    private PersonFilter personFilter;
    
    @ManyToOne
    private Industry industry;

    @ManyToOne
    private JobTitle jobTitle;

    private transient boolean notifyMail;

    private transient boolean notifySMS;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
    private Set<Permission> permissions = new HashSet<Permission>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
    private Set<UserApplicationConfiguration> applicationConfigurations = new HashSet<UserApplicationConfiguration>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
    private Set<UserPreference> preferences = new HashSet<UserPreference>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
    private Set<PasswordHistory> passwordHistorys = new HashSet<PasswordHistory>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
    private Set<PersonSecurityQuestion> securityQuestions = new HashSet<PersonSecurityQuestion>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
    private Set<Event> events = new HashSet<Event>();

	private static final long serialVersionUID = 1L;

	public String getUserName() {
        return this.userName;
    }

	public void setUserName(String userName) {
        this.userName = userName;
    }

	public String getDisplayName() {
        return this.displayName;
    }

	public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

	public Enumeration getPersonType() {
        return this.personType;
    }

	public void setPersonType(Enumeration personType) {
        this.personType = personType;
    }

	public LdapServer getLdapServer() {
        return this.ldapServer;
    }

	public void setLdapServer(LdapServer ldapServer) {
        this.ldapServer = ldapServer;
    }

	public String getPassword() {
        return this.password;
    }

	public void setPassword(String password) {
        this.password = password;
    }

	public String getSalt() {
        return this.salt;
    }

	public void setSalt(String salt) {
        this.salt = salt;
    }

	public String getFirstName() {
        return this.firstName;
    }

	public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

	public String getMiddleName() {
        return this.middleName;
    }

	public void setMiddleName(String middleName) {
        this.middleName = middleName;
    }

	public String getLastName() {
        return this.lastName;
    }

	public void setLastName(String lastName) {
        this.lastName = lastName;
    }

	public String getNamePrefix() {
        return this.namePrefix;
    }

	public void setNamePrefix(String namePrefix) {
        this.namePrefix = namePrefix;
    }

	public JobTitle getJobTitle() {
        return this.jobTitle;
    }

	public void setJobTitle(JobTitle jobTitle) {
        this.jobTitle = jobTitle;
    }
	
	public Industry getIndustry() {
		return industry;
	}

	public void setIndustry(Industry industry) {
		this.industry = industry;
	}

	public String getJobDescription() {
        return this.jobDescription;
    }

	public void setJobDescription(String jobDescription) {
        this.jobDescription = jobDescription;
    }

	public Date getDateOfBirth() {
        return this.dateOfBirth;
    }

	public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

	public Enumeration getGender() {
        return this.gender;
    }

	public void setGender(Enumeration gender) {
        this.gender = gender;
    }

	public Person getCreatedBy() {
        return this.createdBy;
    }

	public void setCreatedBy(Person createdBy) {
        this.createdBy = createdBy;
    }

	public PersonFilter getPersonFilter() {
        return this.personFilter;
    }

	public void setPersonFilter(PersonFilter personFilter) {
        this.personFilter = personFilter;
    }

	public Set<Permission> getPermissions() {
        return this.permissions;
    }

	public void setPermissions(Set<Permission> permissions) {
        this.permissions = permissions;
    }

	public Set<UserApplicationConfiguration> getApplicationConfigurations() {
        return this.applicationConfigurations;
    }

	public void setApplicationConfigurations(Set<UserApplicationConfiguration> applicationConfigurations) {
        this.applicationConfigurations = applicationConfigurations;
    }

	public Set<UserPreference> getPreferences() {
        return this.preferences;
    }

	public void setPreferences(Set<UserPreference> preferences) {
        this.preferences = preferences;
    }

	public Set<PasswordHistory> getPasswordHistorys() {
        return this.passwordHistorys;
    }

	public void setPasswordHistorys(Set<PasswordHistory> passwordHistorys) {
        this.passwordHistorys = passwordHistorys;
    }

	public Set<PersonSecurityQuestion> getSecurityQuestions() {
        return this.securityQuestions;
    }

	public void setSecurityQuestions(Set<PersonSecurityQuestion> securityQuestions) {
        this.securityQuestions = securityQuestions;
    }

	public Set<Event> getEvents() {
        return this.events;
    }

	public void setEvents(Set<Event> events) {
        this.events = events;
    }
	
	
	public String toString() {
        return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }

	public String toJson() {
        return new JSONSerializer().exclude("*.class").deepSerialize(this);
    }

	public static Person fromJsonToPerson(String json) {
        return new JSONDeserializer<Person>().use(null, Person.class).deserialize(json);
    }

	public static String toJsonArray(Collection<Person> collection) {
        return new JSONSerializer().exclude("*.class").deepSerialize(collection);
    }

	public static Collection<Person> fromJsonArrayToPeople(String json) {
        return new JSONDeserializer<List<Person>>().use(null, ArrayList.class).use("values", Person.class).deserialize(json);
    }
}
